#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QDebug>
#include <QMessageBox>
#include "loadingDialog.h"
#include <QHashIterator>
#include "libvcard/vcard.h"
#include "progressdialog.h"
#include "backup_thread.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
        ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    dialog = 0;
    vCardHash contactsPhone;
    vCardHash contactsSim;
    QObject::connect(&mobex,SIGNAL(modeChanged(int)), this, SLOT(showCurrentMode(int)));
    QObject::connect(ui->actionSave_Phonebook, SIGNAL(triggered()),this,SLOT(savePhonebook()));
    QObject::connect(ui->actionSave_SIM_Phonebook, SIGNAL(triggered()),this,SLOT(saveSimPhonebook()));

    QObject::connect(ui->contactsPhone, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(displayItem(QTreeWidgetItem*)));

    ui->statusBar->insertPermanentWidget(0,ui->model);
    ui->statusBar->insertPermanentWidget(1,ui->currentMode);
    ui->contactsPhone->setColumnWidth(0,50);
    ui->contactsPhone->sortByColumn(1,Qt::AscendingOrder);
    ui->contactsSim->setColumnWidth(0,50);
    ui->contactsSim->sortByColumn(1,Qt::AscendingOrder);
    ui->vcBirthDate->setDisplayFormat("dd-MM-yyyy");


    // ui->getPhonebook->setEnabled(true);
    /*
     *Test for vCards

    QString filePath = QDir::homePath().append("/vcard.vcf");
    QFile file(filePath);
    file.open(QIODevice::ReadWrite);
    vCard card = vCard::fromByteArray(file.readAll())[0];
  */
}

MainWindow::~MainWindow()
{
    mobex.closePort();
    delete ui;
    delete dialog;
    qDebug("Destroyed MainWindow");
}


void MainWindow::setPort(QString &port)
{
    ui->modem->setText(port);
}
void MainWindow::setModel(QString &model)
{
    ui->model->setText(model);
}

void MainWindow::showCurrentMode(int mode) {
    bool IS_OBEX = (mode == 2)? true: false;

    switch(mode) {
    case -1:
        ui->currentMode->setText(tr("Cannot open device."));
        break;
    case 0:
        ui->currentMode->setText(tr("No modem found."));
        break;
    case 1:
        ui->currentMode->setText(tr("Open in AT mode"));
        break;
    case 2:
        ui->currentMode->setText(tr("Open in OBEX mode"));
        break;
    }
    ui->getPhonebook->setEnabled(IS_OBEX);//Enable if is in obex mode
    ui->connect->setDisabled(IS_OBEX);//Disable connect button in obex mode
    ui->getSimbook->setEnabled(IS_OBEX);//Enable if is in obex mode
    ui->actionDisconnect->setEnabled(IS_OBEX);//
    ui->actionBackupPhonebook->setEnabled(IS_OBEX);
    ui->actionSave_Phonebook->setEnabled(IS_OBEX);
    ui->actionSave_SIM_Phonebook->setEnabled(IS_OBEX);
}

void MainWindow::openPort() {
    int openState = mobex.openPort(ui->modem->text());
    const QString port = mobex.currentPort();

    ui->statusBar->showMessage(port);
    switch(openState) {
    case -1:
        qDebug() << "Cannot open port "<< port;
        break;
    case 0:
        qDebug() << "Phone not found at " << port;
        break;
    case 1:
        qDebug() << "Open in AT mode" << port;
        ui->model->setText(mobex.checkModel());
        mobex.ObexStart();//Start QMobex session
        break;
    case 2:
        qDebug() << "Open in OBEX mode" << port;
        break;
    }
}
void MainWindow::closePort() {
    contactsPhone.clear();
    contactsSim.clear();
    reloadListPhone();
    reloadListSim();
    ui->model->setText("Unknown");
    mobex.closePort();
}

void MainWindow::loadContactsPhone() {
    dialog = new LoadingDialog();
    dialog->setText(tr("Loading contacts from Phone Memory"));
    dialog->load(&contactsPhone, QMobex::MEMORY_PHONE, &mobex);
    dialog->exec();
    reloadListPhone();
    qDebug() << "Downloaded contacts from phone memory" << contactsPhone.size();
    delete dialog;
    dialog = 0;

    //   int id = phone.contactsDelete(215 ,QMobex::MEMORY_PHONE);
    //      qDebug() << "Deleted contact status:  " << id;
    //contactsPhone.clear();
}
void MainWindow::loadContactsSim() {
    dialog = new LoadingDialog();
    dialog->setText(tr("Loading contacts from SIM Card"));
    dialog->load(&contactsSim, QMobex::MEMORY_SIM, &mobex);
    dialog->exec();
    reloadListSim();
    qDebug() << "Downloaded contacts from sim" << contactsSim.size();
    delete dialog;
    dialog = 0;
}


void MainWindow::reloadList(vCardHash &data, QTreeWidget *view) {
    view->clear();
    //Create iterator
    QHashIterator<int, vCard> iter(data);
    //Create params List
    vCardParamList params;
    while(iter.hasNext()) {//looping list
        iter.next();//Get item
        QTreeWidgetItem *item = new QTreeWidgetItem(view);//create Widget item
        const QVariant id(iter.key());//Get Contact ID
        vCard card = iter.value();//Get vCard data

        //Get First and last name
        QString n = " ";//Default emty name with space
        if (card.contains(VC_NAME)) {
            QStringList name_fields = card.property(VC_NAME).values();
            n.prepend(qoutedPrintableEncode(name_fields.at(vCardProperty::Firstname)));
            n.append(qoutedPrintableEncode(name_fields.at(vCardProperty::Lastname)));
        }
        const QVariant name = n;

        //Get Formated Name
        const QVariant fn = (card.contains(VC_FORMATTED_NAME))? qoutedPrintableEncode(card.property(VC_FORMATTED_NAME).value()) : name; //or name
        //Get Mobile Phon
        params.clear();
        params << vCardParam("HOME") << vCardParam("CELL");
        const QVariant phone_home_cell = (card.contains(VC_TELEPHONE))? card.property(VC_TELEPHONE, params, true).values().join("; ") : QString("");

        //Get Home Phone
        params.clear();
        params << vCardParam("HOME") << vCardParam("VOICE");
        const QVariant phone_home_voice = (card.contains(VC_TELEPHONE))? card.property(VC_TELEPHONE, params, true).values().join("; ") : QString("");

        params.clear();
        params << vCardParam("WORK") << vCardParam("CELL");
        const QVariant phone_work_cell = (card.contains(VC_TELEPHONE))? card.property(VC_TELEPHONE, params, true).values().join("; ") : QString("");

        params.clear();
        params << vCardParam("WORK") << vCardParam("VOICE");
        const QVariant phone_work_voice = (card.contains(VC_TELEPHONE))? card.property(VC_TELEPHONE, params, true).values().join("; ") : QString("");

        item->setData(0,Qt::DisplayRole,id);
        item->setData(1,Qt::DisplayRole,fn);
        item->setData(1,Qt::ToolTipRole,n);

        item->setData(2,Qt::DisplayRole,phone_home_cell);
        item->setData(2,Qt::ToolTipRole,phone_home_voice);
        item->setData(3,Qt::DisplayRole, phone_work_voice);
        item->setData(3,Qt::ToolTipRole, phone_work_cell);
    }
}

void MainWindow::reloadListPhone() {
    ui->tab->setCurrentIndex(0);
    reloadList(contactsPhone,ui->contactsPhone);


}
void MainWindow::reloadListSim() {
    ui->tab->setCurrentIndex(1);
    reloadList(contactsSim, ui->contactsSim);
}


//Convert Quoted printable string to UTF
QString MainWindow::qoutedPrintableEncode(QString data) {
    QByteArray decoded = QByteArray::fromPercentEncoding(data.toAscii(),'=');
    return QString::fromUtf8(decoded.data());
}

void MainWindow::savePhonebook() {
    if(contactsPhone.size() < 1) {//There is no contacts
     ui->statusBar->showMessage(tr("No entries to save. Load phonebook first"), 5000);
     return;
    }
    QString dirToSave = QFileDialog::getExistingDirectory(this,tr("Choose directory to save vCards"),QDir::homePath(), QFileDialog::ShowDirsOnly|QFileDialog::DontUseNativeDialog);
    qDebug() << dirToSave;
    if(QDir(dirToSave).exists() ) {
        QHashIterator<int, vCard> iter(contactsPhone);
        while(iter.hasNext()) {
            iter.next();
            vCard card = iter.value();
            QString id;
            id.setNum(iter.key());
            //Get Formated Name
            QString fn;
            fn = (card.contains(VC_FORMATTED_NAME))? qoutedPrintableEncode(card.property(VC_FORMATTED_NAME).value()) : id;
            QString path = dirToSave + "/" + fn + "_" + id + ".vcf";
            card.saveToFile(path);
            ui->statusBar->showMessage(tr("Saved: ").append(path), 5000);
        }
    }
}


void MainWindow::saveSimPhonebook() {
    QString dirToSave = QFileDialog::getExistingDirectory(this,tr("Choose directory to save vCards"),QDir::homePath(), QFileDialog::ShowDirsOnly|QFileDialog::DontUseNativeDialog);
    qDebug() << dirToSave;
    if(dirToSave.length() > 0 ) {
        QHashIterator<int, vCard> iter(contactsSim);
        while(iter.hasNext()) {
            iter.next();
            vCard card = iter.value();
            QString id;
            id.setNum(iter.key());
            //Get Formated Name
            QString fn;
            fn = (card.contains(VC_NAME))? qoutedPrintableEncode(card.property(VC_NAME).value()) : id;
            QString path = dirToSave + "/" + fn + "_" + id + ".vcf";
            card.saveToFile(path);
        }
    }
}

void MainWindow::backupContacts(QByteArray memory) {
    int total = 0;
    int max = 0;
    if( mobex.contactsCount(total,max,memory)) {

        QString filePath = QFileDialog::getOpenFileName(this,tr("Select file to save contacts"),        QDir::homePath().append("/contacts.txt"),"",0,QFileDialog::DontUseNativeDialog);

        QFile file(filePath);
        if(file.open(QIODevice::WriteOnly)) {

            ProgressDialog *progressdialog;
            progressdialog = new ProgressDialog(this);
            progressdialog->setRange(0, total);
            progressdialog->setWindowTitle("Backup Dialog");
            progressdialog->setText(tr("Backup Phonebook progress"));
            //Create Backuping thread
            BackupThread *bt = new BackupThread(&mobex, &file, QMobex::MEMORY_PHONE);

            QObject::connect(progressdialog, SIGNAL(rejected()), bt,SLOT(abort()));
            QObject::connect(bt,SIGNAL(saved(int)),progressdialog,SLOT(setValue(int)));
            QObject::connect(bt,SIGNAL(finished()),progressdialog,SLOT(accept()));
            bt->start();
            progressdialog->exec();
            while(!bt->isFinished()) {
                qDebug("Waiting for Backup thread finish");
                sleep(1);
            }
            delete progressdialog;
            delete bt;
        }
        else {
            ui->statusBar->showMessage("Cannot open file", 5000);
        }
    }
    else {
        ui->statusBar->showMessage("Cannot get contacts number", 5000);
    }
}

void MainWindow::openLocalFiles() {
    QStringList files = QFileDialog::getOpenFileNames(this,tr("Open vCard files"), QDir::homePath(),tr("vCards (*.vcf) ;; All files (*.*)"), 0,QFileDialog::DontUseNativeDialog);
    qDebug() << files;
    while(!files.isEmpty()) {
        QString file = files.takeFirst();
        contactsFile.append(vCard::fromFile(file));
    }
}

void MainWindow::displayItem(QTreeWidgetItem *item) {
    //Initialize data
    QString displayed_name = "";
    QString first_name = "";
    QString last_name = "";
    QString nick_name = "";
    QString phone_home_cell = "";
    QString phone_home_voice = "";
    QString phone_home_video = "";
    QString phone_work_cell = "";
    QString phone_work_voice = "";
    QString phone_work_video = "";
    QString email_home = "";
    QString email_work = "";
    QString note = "";

    QDate birthday = QDate::currentDate();
    ui->deleteContactPhone->setDisabled(true);

    if(item) {//check if list is not empty
        int id = item->data(0,Qt::DisplayRole).toInt();
        ui->deleteContactPhone->setEnabled(true);
        vCard card = contactsPhone.value(id);
        vCardParamList params;//object to use for params
        //Get Formated Name
        displayed_name = (card.contains(VC_FORMATTED_NAME))? qoutedPrintableEncode(card.property(VC_FORMATTED_NAME).value()) : "";

        //First name and last name
        if(card.contains(VC_NAME)) {
            QStringList name_fields = card.property(VC_NAME).values();
            first_name = (qoutedPrintableEncode(name_fields.at(vCardProperty::Firstname)));
            last_name = (qoutedPrintableEncode(name_fields.at(vCardProperty::Lastname)));
        }
        if(card.contains(VC_NICKNAME)) {
            nick_name=(qoutedPrintableEncode(card.property(VC_NICKNAME).value()));
        }
        //PHONES
        if(card.contains(VC_TELEPHONE)) {
            //Get cell phone
            params.clear();
            params << vCardParam("HOME") << vCardParam("CELL");
            phone_home_cell = card.property(VC_TELEPHONE, params, true).value();
            //Get Home Phone
            params.clear();
            params << vCardParam("HOME") << vCardParam("VOICE");
            phone_home_voice =  card.property(VC_TELEPHONE, params, true).value();
            params.clear();
            params << vCardParam("HOME") << vCardParam("VIDEO");
            phone_home_video =  card.property(VC_TELEPHONE, params, true).value();
            //Get Work phone
            params.clear();
            params << vCardParam("WORK") << vCardParam("CELL");
            phone_work_cell = card.property(VC_TELEPHONE, params, true).value();
            params.clear();
            params << vCardParam("WORK") << vCardParam("VOICE");
            phone_work_voice =  card.property(VC_TELEPHONE, params, true).value();
            params.clear();
            params << vCardParam("WORK") << vCardParam("VIDEO");
            phone_work_voice =  card.property(VC_TELEPHONE, params, true).value();
        }//END PHONES
        //EMAIL
        if(card.contains(VC_EMAIL)) {
            params.clear();
            params  << vCardParam("HOME");
            email_home =  qoutedPrintableEncode(card.property(VC_EMAIL, params).value());
            params.clear();
            params  << vCardParam("WORK");
            email_home =  qoutedPrintableEncode(card.property(VC_EMAIL, params).value());
        }
        //BIRTHDAY
        if(card.contains(VC_BIRTHDAY)) {
            ui->checkBox->setChecked(true);
            birthday = QDate::fromString(card.property(VC_BIRTHDAY).value(), "yyyy-MM-dd");
        }
        else {
            ui->checkBox->setChecked(false);
        }
        //NOTES
        if(card.contains(VC_NOTE)) {
            note = qoutedPrintableEncode(card.property(VC_NOTE).value());
        }
    }//END IF ITEM

    //SET values to form
    ui->vcDisplayedName->setText(displayed_name);//Displayed Name
    ui->vcFirstName->setText(first_name);
    ui->vcLastName->setText(last_name);
    ui->vcNickName->setText(nick_name);
    ui->vcBirthDate->setDate(birthday);
    ui->vcPhoneHomeCell->setText(phone_home_cell);
    ui->vcPhoneHomeVoice->setText(phone_home_voice);
    ui->vcPhoneHomeVideo->setText(phone_home_video);
    ui->vcPhoneWorkCell->setText(phone_work_cell);
    ui->vcPhoneWorkVoice->setText(phone_work_voice);
    ui->vcPhoneWorkVideo->setText(phone_work_video);
    ui->vcEmailHome->setText(email_home);
    ui->vcEmailWork->setText(email_work);
    ui->vcNote->setPlainText(note);
}

void MainWindow::on_actionAbout_Qt_triggered()
{
    QApplication::aboutQt();
}

void MainWindow::on_actionBackupPhonebook_triggered()
{
    backupContacts(QMobex::MEMORY_PHONE);
}



void MainWindow::on_deleteContactPhone_clicked()
{
    QTreeWidgetItem *item = ui->contactsPhone->currentItem();
    if(item) {
        int id = item->data(0, Qt::DisplayRole).toInt();
        if (contactsPhone.contains(id)) {//There is still this ID is data Hash
            QMessageBox::StandardButton confirm = QMessageBox::question(0,"Delete contact", tr("Do you realy want to delete contact?"), QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel);

            if(confirm != QMessageBox::Ok) {
                ui->statusBar->showMessage("Delete contact canceled!");
                return;
            }
           int response = mobex.contactsDelete(id, QMobex::MEMORY_PHONE);
           if(0 == response) {
               contactsPhone.remove(id);
                reloadListPhone();
               ui->statusBar->showMessage("Contact deleted", 5000);
           }
           else {
               ui->statusBar->showMessage("Delete contact from Phone ERROR!", 5000);
               qDebug() << "Error:" << response << "while delete from Phone memory contact id: " << id;
           }
        }
    }
}

void MainWindow::on_deleteContactSim_clicked()
{
    QTreeWidgetItem *item = ui->contactsSim->currentItem();
    if(item) {
        int id = item->data(0, Qt::DisplayRole).toInt();
        QString name = item->text(1);

        if (contactsSim.contains(id)) {//There is still this ID is data Hash
            QMessageBox::StandardButton confirm = QMessageBox::question(0,"Delete contact form SIM", tr("Do you realy want to delete contact ").append(name), QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel);

            if(confirm != QMessageBox::Ok) {
                ui->statusBar->showMessage("Delete contact  canceled!");
                return;
            }
           int response = mobex.contactsDelete(id, QMobex::MEMORY_SIM);
           if(0 == response) {
               contactsSim.remove(id);
                reloadListSim();
               ui->statusBar->showMessage("Contact deleted", 5000);
           }
           else {
               ui->statusBar->showMessage("Delete contact from Phone ERROR!", 5000);
               qDebug() << "Error:" << response << "while delete from Phone memory contact id: " << id;
           }
        }
    }
}
